import 'dart:async';
import 'package:flutter/material.dart';
import 'animation_transition.dart';
import 'constants.dart';

class CustomDialog {
  // 原始Dialog所需参数
  final BuildContext context;
  final Key? key;
  final Color? backgroundColor;
  final double? elevation;
  final Duration insetAnimationDuration;
  final Curve insetAnimationCurve;
  final EdgeInsets? insetPadding;
  final Clip clipBehavior;
  final ShapeBorder? shape;
  // 将child widget进行改造所需icon, title,content,actions

  final Alignment alignment;
  final DialogHeader header;
  final DialogBody body;
  final DialogFooter footer;
  final DialogBarrier barrier;
  final DialogTransition transition;
  final Decoration? decoration;
  final BoxConstraints? constraints;
  final double? width;
  CustomDialog(this.context,
      {this.key,
      this.backgroundColor,
      this.elevation,
      this.insetAnimationDuration = const Duration(milliseconds: 100),
      this.insetAnimationCurve = Curves.decelerate,
      this.insetPadding,
      this.clipBehavior = Clip.none,
      this.shape,
      this.alignment = Alignment.center,
      this.header = const DialogHeader(),
      required this.body,
      this.footer = const DialogFooter(),
      this.barrier = const DialogBarrier(),
      this.transition = const DialogTransition(),
      this.decoration = const BoxDecoration(
        boxShadow: [
          BoxShadow(
              color: Colors.black54, //阴影x轴偏移量
              blurRadius: 8, //阴影模糊程度
              spreadRadius: 0 //阴影扩散程度
              )
        ],
      ),
      this.constraints,
      this.width});
  Future show() async {
    return await showGeneralDialog(
        context: context,
        pageBuilder: (BuildContext buildContext, Animation<double> animation,
            Animation<double> secondaryAnimation) {
          return _buildDialog();
        },
        barrierDismissible: barrier.barrierDismissible,
        barrierLabel:
            MaterialLocalizations.of(context).modalBarrierDismissLabel,
        barrierColor: barrier.barrierColor ?? const Color.fromRGBO(0, 0, 0, 75),
        useRootNavigator: true,
        transitionDuration: transition.duration,
        transitionBuilder: (
          BuildContext context,
          Animation<double> animation,
          Animation<double> secondaryAnimation,
          Widget child,
        ) =>
            transition.builder == null
                ? _showAnimation(animation, secondaryAnimation, child)
                : transition.builder!(
                    context, animation, secondaryAnimation, child));
  }

  // Will be added in next version.
  Future<void> dismiss() async {
    Navigator.of(context, rootNavigator: true).pop();
  }

  // 构建dialog
  Widget _buildDialog() {
    final Widget child = Align(
        alignment: alignment,
        child: Container(
            width: width ?? double.infinity,
            decoration: decoration,
            constraints: constraints ??
                BoxConstraints(
                    maxWidth: width ?? double.infinity,
                    maxHeight: double.infinity),
            child: SingleChildScrollView(
              child: Dialog(
                  key: key,
                  backgroundColor: backgroundColor,
                  elevation: elevation,
                  insetAnimationDuration: insetAnimationDuration,
                  insetAnimationCurve: insetAnimationCurve,
                  insetPadding: insetPadding,
                  clipBehavior: clipBehavior,
                  shape: shape ?? _defaultShape(),
                  child: _getChild()),
            )));
    return footer.onWillPopActive
        ? WillPopScope(onWillPop: () async => false, child: child)
        : child;
  }

  Widget _getChild() {
    return Column(children: [_getHeader(), _getBody(), _getFooter()]);
  }

  Widget _getHeader() {
    Widget headerWidget = header.title.isNotEmpty
        ? Text(header.title,
            maxLines: 1,
            overflow: TextOverflow.ellipsis,
            style: header.titleStyle)
        : const SizedBox.shrink();
    if (footer.hasClose) {
      headerWidget = Row(
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [Expanded(flex: 1, child: headerWidget), _getCloseButton()],
      );
    }
    if (footer.hasClose) {
      return Container(
          padding: header.padding,
          alignment: header.alignment,
          constraints: header.constraints,
          child: headerWidget);
    } else {
      return const SizedBox.shrink();
    }
  }

  Widget _getBody() {
    List<Widget> response = [];
    response.add(_getIcon());
    response.add(body.content);
    Widget child = Column(
      crossAxisAlignment: CrossAxisAlignment.start,
      mainAxisAlignment: MainAxisAlignment.start,
      children: [...response],
    );
    return Container(
        padding: body.padding,
        decoration: body.decoration,
        constraints: BoxConstraints(
          maxHeight: body.isScorll ? body.scorllHeight : double.infinity,
        ),
        child: SingleChildScrollView(child: child));
  }

  // 获取到action
  Widget _getFooter() {
    List<Widget> widgetButtons = [];
    if (footer.isVisible) {
      if (footer.actions != null) {
        footer.actions?.forEach(
          (button) {
            widgetButtons.add(button);
          },
        );
      } else {
        widgetButtons.add(OutlinedButton(
          child: const Text(
            'cancel',
            style: TextStyle(color: Colors.white, fontSize: 20),
          ),
          onPressed: () => Navigator.pop(context),
        ));
      }
    }
    return Container(
        // color: Colors.yellow,
        padding: footer.padding,
        decoration: footer.decoration,
        // height: 32,
        child: Row(
            mainAxisAlignment: MainAxisAlignment.spaceAround,
            crossAxisAlignment: CrossAxisAlignment.center,
            children: widgetButtons));
  }

  Widget _getCloseButton() {
    return GestureDetector(
      behavior: HitTestBehavior.opaque,
      onTap: () {
        if (footer.closeFunction == null) {
          Navigator.of(context, rootNavigator: true).pop();
        } else {
          footer.closeFunction!();
        }
      },
      child: footer.close ??
          Container(
            width: 20,
            height: 20,
            margin: const EdgeInsets.only(left: 5),
            decoration: const BoxDecoration(
              image: DecorationImage(
                image: AssetImage(
                  '${assetsPath}close.png',
                ),
              ),
            ),
          ),
    );
  }

  Widget _getIcon() {
    Widget child;
    if (body.icon != null) {
      child = body.icon!;
    } else {
      String? iconName;
      switch (body.iconType) {
        case IconTypes.success:
          iconName = 'success';
          break;
        case IconTypes.error:
          iconName = 'error';
          break;
        case IconTypes.info:
          iconName = 'info';
          break;
        case IconTypes.warning:
          iconName = 'warning';
          break;
        case IconTypes.none:
          break;
      }
      if (iconName != null) {
        child = Image.asset('${assetsPath}icon_$iconName.png');
      } else {
        child = const SizedBox.shrink();
      }
    }
    return Container(
      padding: const EdgeInsets.only(bottom: 15),
      alignment: Alignment.center,
      child: child,
    );
  }

  ShapeBorder _defaultShape() {
    return RoundedRectangleBorder(
      borderRadius: BorderRadius.circular(8),
      side: const BorderSide(
        color: Colors.black12,
      ),
    );
  }

  // Shows alert with selected animation
  _showAnimation(animation, secondaryAnimation, child) {
    switch (transition.type) {
      case AnimationType.fromRight:
        return AnimationTransition.fromRight(
            animation, secondaryAnimation, child);
      case AnimationType.fromLeft:
        return AnimationTransition.fromLeft(
            animation, secondaryAnimation, child);
      case AnimationType.fromBottom:
        return AnimationTransition.fromBottom(
            animation, secondaryAnimation, child);
      case AnimationType.grow:
        return AnimationTransition.grow(animation, secondaryAnimation, child);
      case AnimationType.shrink:
        return AnimationTransition.shrink(animation, secondaryAnimation, child);
      case AnimationType.fromTop:
        return AnimationTransition.fromTop(
            animation, secondaryAnimation, child);
    }
  }
}
